package design_pattern.ObserveThread.plus;

import java.util.List;

/**
 * @Author: 蔡翔
 * @Date: 2019/10/31 21:07
 * @Version 1.0
 */
public class ThreadLifeCycleObserver implements LifeCycleListener {
    //因为不止一个线程调用 ThreadLifeCycleObserver 所以要给它加锁。
    private final Object LOCK = new Object();
    private Integer aaw = 1;
    //业务-批量查询
    public void concurrentQuery(List<String> ids){
        if(ids == null && ids.isEmpty()){
            return;
        }

        //注意这里的this 指的是ThreadLifeCycleObserver 因为这个类实现了LifeCycleListener
        ids.stream().forEach(id->new Thread(new ObservableRunnable(this) {
            //之所以要重写 run 方法，是因为ObservableRunnable()对象中，没有写run方法。
            @Override
            public void run() {
                // 注意在外面 new 了一个ObservableRunnable对象是需要重写 里面run方法的。
                // 这个run 方法里面其实就是ObservableRunnable()对象的域了。所以自然而然可以用notifyChange()方法
                try {
                    // 这里的Thread.currentThread() 就是上面forEach出来的线程。
                    notifyChange(new RunnableEvent(RunnableState.RUNNING,Thread.currentThread(),null));
                    System.out.println("query for the id"+id);
                    Thread.sleep(1000L);
                    // 用 1/0 来模拟一个异常。
                    Integer z = 1/0;
                    notifyChange(new RunnableEvent(RunnableState.DONE,Thread.currentThread(),null));
                }catch (Exception e){
                    notifyChange(new RunnableEvent(RunnableState.ERROR,Thread.currentThread(),e));

                }
            }
        },id).start());
    }
    @Override
    public void onEvent(ObservableRunnable.RunnableEvent event) {
        //在这个方法里面 可以写 一些 ，，对应某种监听的方法。
        //(上接)注意这里要加 synchronize 因为上面 new 出的ObservableRunnable传进去的都是同一个this。因为同时又多个线程在跑
        //(上接)写这个onEvent的意义就在于 监控每个线程（多个线程）跑的情况（这个很重要，成功、失败 或者异常）
        synchronized (LOCK){
            System.out.println("The runnable ["+event.getThread().getName()+"] data changed and state is ["+event.getState()+"]");
            //如果失败了
            if(event.getCause()!=null){
                System.out.println("The runnable ["+event.getThread().getName()+"] process failed.");
                event.getCause().printStackTrace();
            }
        }
    }
}
